package com.jbp.utils;
import com.jbp.model.GiftLot;

import java.math.BigDecimal;
import java.util.*;

/**飞马抽奖工具*/
public class LuckyUtil2 {

    //普通奖池生成
    public static LinkedList<Integer> generate(List<GiftLot> giftLots) {
        LinkedList<Integer> list =new LinkedList<>();
        for (int i = 0; i < giftLots.size(); i++) {
            GiftLot giftLot = giftLots.get(i);
            if (giftLot.getGiftNum()<=0) {
                continue;
            }
            if (list.size()==0) {
                //第一位直接插入
//                System.out.println((i+1)+":"+property.getPrice()+"钻"+property.getCount()+"个 直接插入");
                Integer[] gifts1 = new Integer[giftLot.getGiftNum()];
                Arrays.fill(gifts1, giftLot.getGiftId());
                list.addAll(Arrays.asList(gifts1));
            } else if (i==giftLots.size()-1 && giftLot.getGiftNum()==1) {
//                System.out.println((i+1)+":"+property.getPrice()+"钻"+property.getCount()+"个，原奖池共 "+list.size()+"， 将"+property.getPrice()+"奖品放在奖池最后");
                //最后一个大奖随机插入奖池的后20%
                int start = (int) (list.size()*0.8);
                int end = list.size()-1;
                if (end<=start) {
                    list.add(giftLot.getGiftId());
                } else {
                    int index = new Random().nextInt(end - start) + start;
                    list.add(index, giftLot.getGiftId());
                }
            } else{
                if (giftLot.getGift().getCoin()!=52000 && giftLot.getGift().getCoin()!=99999) {
                    int count = giftLot.getGiftNum();
                    for (int j = count; j > 0; j--) {
                        int start = 0;
                        int end = list.size()-1;
                        int index = 0;
                        if (end - start > 0) {
                            index = new Random().nextInt(end - start) + start;
                        }
                        list.add(index, giftLot.getGiftId());
                    }
                } else {
                    //将当前奖池平分为 count份
                    int count = giftLot.getGiftNum();
                    //后面每份长度len, 前面每份长度len+1
                    int len = list.size() / giftLot.getGiftNum();
                    //前面多少份
                    int pre = list.size() - len * giftLot.getGiftNum();
                    //后面多少份
                    int last = giftLot.getGiftNum() - pre;
//                System.out.println((i+1)+":"+property.getPrice()+"钻"+count+"个，原奖池共 "+list.size()+
//                        "将原奖池分为"+count+"份， 前面"+pre+"份"+(len+1)+"个， 后面"+ last+"份"+len+"个，\n" +
//                        "每份随机插入一个"+property.getPrice()+"钻礼物");
                    for (int j = count; j > 0; j--) {
                        int start = (len + 1) * (j - 1);
                        int end = (len + 1) * j;
                        if (j > pre) {
                            start = start - (j - pre - 1);
                            end = end - (j - pre);
                        }
                        int index = new Random().nextInt(end - start) + start;
//                    System.out.println("随机数范围："+start+" - "+end + " - index="+index);
                        list.add(index, giftLot.getGiftId());
                    }
                }
            }
        }
        return list;
    }

    //其他奖池生成  全随机
    public static List<Integer> generateOther(List<GiftLot> giftLots) {
        ArrayList<Integer> list =new ArrayList<>();
        for (int i = 0; i < giftLots.size(); i++) {
            GiftLot giftLot = giftLots.get(i);
            for (int j = 0; j < giftLot.getGiftNum(); j++) {
                list.add(giftLot.getGiftId());
            }
        }
        //打乱
        Collections.shuffle(list);

        return list;
    }

    public static void main(String[] args) {
//        Map<Integer, Integer> map = getGiftCoinfig3();
//        printConfig(map);

       System.out.println("------------------奖池3-------------------");
        Map<Integer, Integer> map = getGiftCoinfig();
        printConfig(map);
        ArrayDeque<Integer> gifts = generate(map);
        int times = 5000;
        printBl(gifts, times);
        printTj(gifts, times);
//        ArrayDeque<Integer> gifts2 = generate(map);
//        printTj(gifts2, 100);
//        ArrayDeque<Integer> gifts3 = generate(map);
//        printTj(gifts3, 1000);
 /*
        System.out.println("------------------奖池2-------------------");
        Map<Integer, Integer> map2 = getGiftCoinfig2();
        ArrayDeque<Integer> gifts21 = generate(map2);
        printTj(gifts21, 50);
        ArrayDeque<Integer> gifts22 = generate(map2);
        printTj(gifts22, 500);
        ArrayDeque<Integer> gifts23 = generate(map2);
        printTj(gifts23, 5000);*/
    }

    //打印统计
    private static void printTj(ArrayDeque<Integer> gifts, int times){
        List<Double> bls = new ArrayList<>();
        while (gifts.size()>=times) {
            List<Integer> lucks = new ArrayList<>();
            for (int i = 0; i < times; i++) {
                lucks.add(gifts.pop());
            }
            int cc = lucks.stream().mapToInt((i) -> i).sum();
            BigDecimal bl = BigDecimal.valueOf(cc * 100).divide(BigDecimal.valueOf(times * 20), 4, BigDecimal.ROUND_HALF_UP);
            bls.add(bl.doubleValue());
        }
        System.out.println("总计抽奖:"+bls.size()+"回， 每回"+times+"次");
        System.out.println("爆率<30:"+bls.stream().filter(bl->bl<30).count()+"次");
        System.out.println("30<=爆率<40:"+bls.stream().filter(bl->bl>=30 && bl<40).count()+"次");
        System.out.println("40<=爆率<50:"+bls.stream().filter(bl->bl>=40 && bl<50).count()+"次");
        System.out.println("50<=爆率<60:"+bls.stream().filter(bl->bl>=50 && bl<60).count()+"次");
        System.out.println("60<=爆率<70:"+bls.stream().filter(bl->bl>=60 && bl<70).count()+"次");
        System.out.println("70<=爆率<80:"+bls.stream().filter(bl->bl>=70 && bl<80).count()+"次");
        System.out.println("80<=爆率<90:"+bls.stream().filter(bl->bl>=80 && bl<90).count()+"次");
        System.out.println("90<=爆率<100:"+bls.stream().filter(bl->bl>=90 && bl<100).count()+"次");
        System.out.println("100<=爆率<110:"+bls.stream().filter(bl->bl>=100 && bl<110).count()+"次");
        System.out.println("110<=爆率<120:"+bls.stream().filter(bl->bl>=110 && bl<120).count()+"次");
        System.out.println("120<=爆率<130:"+bls.stream().filter(bl->bl>=120 && bl<130).count()+"次");
        System.out.println("130<=爆率<140:"+bls.stream().filter(bl->bl>=130 && bl<140).count()+"次");
        System.out.println("爆率>=140:"+bls.stream().filter(bl->bl>=140).count()+"次");
    }
    //打印爆率
    private static void printBl(ArrayDeque<Integer> gifts, int times){
        while (gifts.size()>=times) {
            List<Integer> lucks = new ArrayList<>();
            for (int i = 0; i < times; i++) {
                lucks.add(gifts.pop());
            }
            int cc = lucks.stream().mapToInt((i) -> i).sum();
            BigDecimal bl = BigDecimal.valueOf(cc * 100).divide(BigDecimal.valueOf(times * 20), 4, BigDecimal.ROUND_HALF_UP);

            System.out.println("抽奖"+times+"次 投入:"+times*20+" 产出："+cc + "  爆率:"+bl);
        }
    }

    private static ArrayDeque<Integer> generate(Map<Integer, Integer> map){
        ArrayDeque<Integer> queue = new ArrayDeque<>();
        ArrayList<Integer> list =new ArrayList<>();
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            for (int j = 0; j < entry.getValue(); j++) {
                list.add(entry.getKey());
            }

        }
        //打乱
        Collections.shuffle(list);
        queue.addAll(list);
        return queue;
    }
    private static void printConfig(Map<Integer, Integer> map) {
        //总价值
        long totalCoin = map.entrySet().stream().mapToInt(e -> e.getKey()*e.getValue()).sum();
        //总数量
        long totalSize = map.values().stream().mapToInt(v->v).sum();
        double zbl = BigDecimal.valueOf(totalCoin).divide(BigDecimal.valueOf(totalSize*20), 6, BigDecimal.ROUND_HALF_UP).doubleValue();

        for (Map.Entry<Integer, Integer> e : map.entrySet()) {
            double bl = BigDecimal.valueOf(e.getValue() * 100).divide(BigDecimal.valueOf(totalSize), 6, BigDecimal.ROUND_HALF_UP).doubleValue();
            double zb = BigDecimal.valueOf(e.getValue() * e.getKey() * 100).divide(BigDecimal.valueOf(totalCoin), 6, BigDecimal.ROUND_HALF_UP).doubleValue();

            System.out.println(e.getKey()+"钻  "+ e.getValue()+"个   "+" 爆率:"+ bl +"    占比:"+zb + "");
//            int count = 70552421;
//            System.out.println(e.getKey()+"钻  "+ (int)(bl*1d/100*count));
        }
        System.out.println("总数量："+totalSize+"  总价值:"+totalCoin+"  总爆率："+zbl);
    }

    private static Map <Integer, Integer> getGiftCoinfig(){
        Map <Integer, Integer> map = new LinkedHashMap<>();
        /*map.put(1, 122198);
        map.put(10, 18136);
        map.put(20, 4000);
        map.put(52, 1500);
        map.put(99, 1050);
        map.put(199, 880);
        map.put(520, 1622);
        map.put(1000, 280);
        map.put(1888, 140);
        map.put(5200, 156);
        map.put(10000, 32);
        map.put(18888, 3);
        map.put(33440, 2);
        map.put(52000, 1);*/

        map.put(1, 121189);
        map.put(10, 18136);
        map.put(20, 4000);
        map.put(52, 3000);
        map.put(99, 1050);
        map.put(199, 880);
        map.put(520, 850);
        map.put(1000, 400);
        map.put(1888, 280);
        map.put(3344, 100);
        map.put(5200, 80);
        map.put(10000, 29);
        map.put(18888, 3);
        map.put(33440, 2);
        map.put(66666, 1);
        return map;
    }
}

class UserLog{
    int totalPay;
    int totalIncome;
}


